-- G51FUN Coursework 2 - Database Systems
--
-- Rory Holland, Marvin Plummeridge
-- psydrh1@nottingham.ac.uk, mbycrmwp@nottingham.ac.uk

type Table	= [(Key,Value)]	-- A list of tuples
type Key	= String
type Value	= String

-- Exercise 1
blank	:: Table
blank		= []

-- Exercise 2

add				:: Key -> Value -> Table -> Table
add	k v t		= 	if exists k t then
						replaceValue k v t
					else 
						t ++ [(k, v)]
						
-- Helper function
-- list comprehension, elem
exists			:: Key -> Table -> Bool
exists "" t		=	False
exists k []		=	False
exists k (t:ts)	=	if (k == fst t) then
						True
					else
						exists k ts						
						
-- Helper function
replaceValue			:: Key -> Value -> Table -> Table
replaceValue k v []		=	[]
replaceValue k v (t:ts)	=	if (k == fst t) then
								[(k, v)] ++ replaceValue k v ts 
							else
								[t] ++ replaceValue k v ts
	
	
-- Exercise 3
-- list comprehension 
value	 :: Key -> Table -> Value
value k []		=	"No entry"
value k (t:ts)	=	if (k == fst t) then
						snd t
					else
						value k ts
								
-- Exercise 4
-- list comprehension 
remove	 :: Key -> Table -> Table
remove k []		= []
remove k (t:ts) =	if (k == fst t) then
						remove k ts 
					else
						[t] ++ remove k ts

-- Exercise 5

display :: Table -> IO()
display []		= 	putStr "Empty"
display ts		=	seqn [putStrLn (fst t++" = "++snd t) | t <- ts]

-- Helper function
-- http://www.haskell.org/tutorial/io.html (7.2)

seqn        :: [IO ()] -> IO ()
seqn        =  foldr (>>) (return ())

-- Exercise 6

save :: Table -> IO()
save t = writeFile "database" (loadDBtoString t)

-- Helper function
loadDBtoString :: Table -> String
loadDBtoString [] = []
loadDBtoString (t:ts) = "/"++fst t++"="++snd t++ loadDBtoString ts

-- Exercise 7

load :: IO Table
load = do {
		x <- readFile "database";
		let y = work (tail (split x '/'));
			in return y;
			--show(work (tail (split x '/')));
			--return y;
		}

work :: [String] -> Table
work [] = []
work (x:xs) = [(head (split x '='), last (split x '='))] ++ work xs
		
		
split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
   | c == delim = "" : rest
   | otherwise = (c : head rest) : tail rest
   where
       rest = split cs delim

-- Exercise 8 (main)

loop	::	Table -> IO()
loop t = do
  putStr "Command : "
  c <- getLine
  case c of

		"add"	->	do
					putStr "Key   : "
					k <- getLine
					putStr "Value : "
					v <- getLine
					loop (add k v t)
		"display"->	do
					display t
					loop t
				  
		"value"->	do
					putStr "Key : "
					k <- getLine
					putStrLn(value k t)
					loop t
				  
		"remove"->	do
					putStr "Key   : "
					k <- getLine
					loop (remove k t)
				  
		"save"	->	do
					putStrLn "Saved"
					save t
					loop t
				  
		"clear"	->	do
					putStrLn "You said clear"
					putStrLn "Cleared"
					loop blank
				  
		"load"	->	do
					nt <- load
					putStrLn "Loaded"
					loop nt
				  
		"quit"	->	putStrLn "Goodbye"
		_		-> 	do
					putStrLn "Invalid option"
					loop t

	
		



main :: IO()
main = loop blank

			

